<!-- 对话模式 -->
<template>
  <div v-if="contentLoadOk" :class="{'quan-textarea': quanbtn}">
    <div v-if="talkListCon.length === 0" class="home-ri-top flex items-center justify-between">
      <slot name="top"></slot>
    </div>
    <!-- 对话 -->
    <div class="talk-content" :class="{on : talkListCon.length > 0}">
    
      <zb-scroll ref="zbScrollRef" :isend="answerStatus === 2">
        <dl class="talk-content-list">
          <!-- <zb-markdown content="$ E = mc^2 $"></zb-markdown> -->
          <div v-for="(item, index) in talkListCon" :key="index">
            <dd class="item w">
              <div class="intro">
                <pre class="pre" v-html="item.questions"></pre>
              </div>
            </dd>
            <!-- answerStatus 当前按钮状态 0-无发送内容， 1-回答中 2-回答结束 3-中断回答 {{answerStatus}}--{{curLink}} -->
            <dd class="item h">
              <div class="intro">
                <zb-markdown :content="item.answers" :ing="answerStatus == 1 ? true : false" :last="index === talkListCon.length - 1" />
                <div class="stop flex items-center">
                  <el-button v-if="answerStatus == 1 && index === talkListCon.length - 1" class="text-tx-regular" @click="stopTalk" link><icon name="el-icon-VideoPause" /><span>停止生成</span></el-button>
                  <el-button v-if="answerStatus != 1 || index < talkListCon.length - 1" class="text-tx-regular talk-btn" link @click="sendSubmitAgain(item.questions)"><icon name="el-icon-Refresh" /><span>重新生成</span></el-button>
                  <el-button class="text-tx-regular talk-btn" link @click="handleCopy(item.answers)"><icon name="el-icon-DocumentCopy" /><span>复制</span></el-button>
                </div>
              </div>
            </dd>
          </div>
          
        </dl>
        
      </zb-scroll>
    </div>
    
    <!-- 底部输入框 -->
    <div class="bottom-box" :class="{on : talkListCon.length > 0}" >
      <el-button link class="create-btn local-icon-new" @click="clearFun()">
        <icon name="local-icon-new" size="18" />
        新建对话
      </el-button>
      <div class="relative send-bottom">
        <el-input type="textarea" class="send-textarea" resize="none" v-model="send_content" placeholder="请输入内容" @keydown="handleKeydown" :autosize="{minRows: 3, maxRows:6}" :maxlength="maxlen" @input="handleInput" />
        <div class="submit-box">
          <div class="send-ziyuan" @click="pupRef?.open()">
            <span>{{aiziyuanList.find(n => n.id == aiziyuanId).name}}</span>
            <icon name="local-icon-ArrowDownBold" color="#000" />
            <el-select v-model="aiziyuanId">
              <el-option v-for="item in aiziyuanList" :key="item.id" :disabled="!item.show" :value="item.id" :label="item.name"></el-option>
            </el-select>
          </div>
          <!-- answerStatus 当前按钮状态 0-无发送内容， 1-回答中 2-回答结束 3-中断回答 -->
          <span class="sendCan" :class="{on: answerStatus == 1 || sendCan}" @click="sendSubmit(send_content)">
            <span v-if="answerStatus == 1" class="curAnswerStop"></span>
            <icon v-else name="local-icon-send" color="#fff" :size="18" />
          </span>
          <span v-if="curRows > 2" class="quan" @click="quanbtn = !quanbtn">
            <img v-if="!quanbtn" src="@/assets/images/open-area.svg" class="icon" alt="">
            <img v-else src="@/assets/images/open-area2.svg" class="icon" alt="">
          </span>
        </div>
      </div>
      <div class="form-tips mt-2 text-center text-line1">测试产生的内容由人工智能模型输出，内容的正确性及完整性无法保证，不代表我们的态度或观点。</div>
    </div>
    <!-- 关联问题 -->
    
    <div v-if="talkListCon.length === 0" class="link-box">
      <div class="title"><img src="@/assets/images/tip.png" class="icon" alt=""><span>你可以这么问我</span></div>
      <dl class="link-list">
        <dd v-for="item in getWebsite.question" :key="item.id" class="item" @click="kuajieSend(item.question)">
          <div class="name text-line1">{{item.title}}</div>
          <div class="intro text-line2 text-tx-secondary">{{item.question}}</div>
        </dd>
      </dl>
    </div>
    
  </div>
  
  <!-- 声音 -->
  <zb-ai-audio ref="audioRef" />
  <!-- ai资源手机端-弹窗 -->
  <div class="model-box wap">
    <zb-pup title="选择模型" ref="pupRef">
      <div class="ai-ziyuan-list">
        <el-scrollbar height="100%">
          <dl class="">
            <dd v-for="(item, index) in aiziyuanList" :key="index" class="item" @click="closeZiyuanFun(item)" :class="{on : sendData.sourceModel == item.id, un: !item.show}">
              <div class="name text-line1">{{item.name}}</div>
              <div class="intro text-line1 text-tx-placeholder">{{item.intro}}</div>
            </dd>
          </dl>
        </el-scrollbar>
      </div>
    </zb-pup>
  </div>
</template>

<script lang="ts" setup>
  import { TopicHistoryApi, createTopicApi} from '@/api/app';
  import { copy } from '@/utils/util';
  import { ElMessage } from 'element-plus'
  import { ref, computed, reactive, onUnmounted, watch, nextTick } from 'vue';
  import { socketConnect, connect, disconnect, sendMsg, printText, printAddEnd, printAddCon, stopchat, getRandomString } from '@/utils/useSocket1';
  import { useAppStore } from '@/stores/app'
  import { loginShow } from '@/utils/weChat'
  const useStore = useAppStore();
  const getWebsite = computed(() => useStore?.getWebsite);
  
  const props = defineProps({
    creat:{
      type:Boolean,
      default:false,  // 对话历史id
    },
    id:{
      type:Number,
      default:0,  // 对话历史id
    },
  })
  const curRows = ref(1)
  const handleInput = () => {
    curRows.value = send_content.value.length/20;
  }
  const quanbtn = ref(false);
  const zbScrollRef = ref(); // 设置滚动条始终在最下面用的
  const contentLoadOk = ref(true)
  const getTalkCon =  (id:number) => {
    if(id === 0) return;
    contentLoadOk.value = false;
    TopicHistoryApi({id: id, limit:500}).then(async (res:any)=>{
      console.log(res, zbScrollRef.value)
      contentLoadOk.value = true;
      talkListCon.value = res.data;
      await nextTick()
      zbScrollRef.value?.setData(getRandomString())
    }).catch(() =>{
      contentLoadOk.value = true;
    })
  }
  // 链接socket 
  const printData = ref<string>(``); // 需要打印的全部内容 => 当前的回答内容
  const printEnd = ref(0); // 0-未打印， 1-打印中, 2-打印结束
  
  const curToken = ref()
  const sendData = reactive({
    msg:'', // 内容
    topic:'', // 历史对话id
    type:1, // 对话
    sourceModel:1, // 资源id
  })
  const audioRef = ref(); // 语音
  const socketInit = () => {
    socketConnect((res:any)=>{
      if(res.code == 1){
        printData.value+=res.msg; // 本次数据流+过去的 = 需要打印的所有数据
        printAddCon(printData.value); // 向打印机中传递最新的数据
        if(printEnd.value != 0) return; // 只有未打印的状态才能执行打印机效果
        audioRef.value?.playFun(1)
        printText((msg:string) => {
          talkListCon.value[talkListCon.value.length - 1].answers= msg; // 最后一条回答的内容
          zbScrollRef.value?.setData(msg)
        }, (e:number) =>{
          printEnd.value = e; // 监听当前打印的状态
        });
      }else if(res.code == 2){
        console.log('---本次打印结束',talkListCon.value.length, printData.value)
        printAddEnd(); // 通知打印机 数据流结束  + 中断scoket
        answerStatus.value = 2;
        printData.value = '';
        emits('getTalk', {talkLen: talkListCon.value.length});
        if(talkListCon.value.length === 1){
          emits('sendFirst', 0, 'del');
        }
      }else if(res.code == 0){
        ElMessage.error(res.errmsg)
      }
    }, async (agin:any) =>{
      if(curToken.value == agin) return;
      if(talkListCon.value.length === 1){ // 当前对话列表是空的 则先新建对话然后再发送消息
        const res = await createTopicApi();
        sendData.topic = res.id;
        emits('sendFirst', res.id, 'add');
        sendMsgFun();
      }else{
        sendData.topic = `${props.id}`;
        sendMsgFun();
      }
      answerStatus.value = 1;
      console.log('重连成功--------------------------------', answerStatus.value)
      curToken.value = agin;
    })
  }
  
  const sendMsgFun = () => {
    printData.value = '';
    printEnd.value = 0;
    audioRef.value?.playFun();
    sendMsg(sendData);
    
  }
  socketInit();
  const maxlen = 8000; // 提问最大数量
  const aiziyuanList = ref([
    {id:1, name:'星火4.0 Turbo', show:true, intro:'我可以帮你搜索、答疑、分析、写作、提建议。请把你的需求'},
    {id:2, name:'DeepSeek-R1', show:false, intro:'适合内容创作、对比判断知识问答零逾期，具备超强的'},
    {id:3, name:'DeepSeek-V3', show:false, intro:'在数学、代码、自然语言推理等任务上性价比比肩'},
  ])
  const aiziyuanId = ref(1); // 资源id
  const aiziyuanShow = ref(false);
  const pupRef = ref()
  const closeZiyuanFun = (item:any) =>{
    if(!item.show) return ElMessage.error('暂未开放')
    sendData.sourceModel = item.id;
    aiziyuanShow.value = false;
  }
  const send_content = ref(''); // 发送内容
  const sendCan = computed(()=>{
    return send_content.value.length > 0
  })
  // 发送对话
  const answerStatus = ref(0); // 当前按钮状态 0-无发送内容， 1-回答中 2-回答结束 3-中断回答， 4 - 终端中
  const talkListCon = ref<{questions:string, answers:string, markDownHtml:string}[]>([]); // 对话内容
  const emits = defineEmits(['getTalk', 'sendFirst']);
  // 快捷发问
  const kuajieSend = (askcon: string) => {
    send_content.value = askcon;
  }
  // 发送消息
  const sendSubmit = async (askcon: string = send_content.value) => {
    if( !loginShow() ) return; // 没有登录直接不执行后面逻辑
    if(answerStatus.value === 1) { printAddEnd(); answerStatus.value = 0; } // 通知打印机 数据流结束  + 中断scoket 
    if(!sendCan.value) return;
    sendData.msg = askcon;
    connect().then(()=>{
      answerStatus.value = 2; // 结束对话
      printEnd.value = 2; // 打印结束
    })
    send_content.value = ''; // 置空输入框内容
    answerStatus.value = 1; // 按钮变成 -- 回答中 -- 状态
    quanbtn.value = false;
    talkListCon.value.push({ questions:askcon, answers:'', markDownHtml:''}); // 对话的问题
  }
  
  // 重新生成
  const sendSubmitAgain = (askcon: string) => {
    send_content.value = askcon;
    sendSubmit(askcon);
  }
 
  // 中断对话
  const stopTalk = () => {
    printEnd.value = 2; // 打印结束
    stopchat().then(() =>{
      answerStatus.value = 3
    })
  }
  // 创建新对话
  const creatNewTalk = () => {
     talkListCon.value = [];
  }
  const handleCopy = (con:string) => {
    copy(con)
  }
  
  // 清除对话
  const clearFun = () => {
    talkListCon.value = []
  }
  
  // 处理 keydown 事件
  const handleKeydown = (event: KeyboardEvent): void => {
    console.log('event.key-====', event.key)
    // 检查是否按下了 Ctrl + Enter
    if ( ( event.shiftKey || event.ctrlKey ) && event.key === 'Enter') {
      // 阻止默认行为（避免提交表单等）
      event.preventDefault();
      // 手动插入换行符
      insertLineBreak(event);
    } 
    // 检查是否只按下了 Enter
    else if (event.key === 'Enter' && !event.ctrlKey) {
      // 阻止默认行为
      event.preventDefault();
      // 调用发送方法
      sendSubmit(send_content.value);
    }
  };
  
  // 插入换行符的方法
  const insertLineBreak = (event: KeyboardEvent): void => {
    const target = event.target as HTMLTextAreaElement;
    const { value, selectionStart, selectionEnd } = target;
  
    // 在光标位置插入换行符
    const before = value.substring(0, selectionStart);
    const after = value.substring(selectionEnd);
    send_content.value = before + '\n' + after;
  
    // 更新光标位置
    setTimeout(() => {
      target.selectionStart = target.selectionEnd = selectionStart + 1;
    }, 0);
  };
  
  const contentRef = ref()
  watch(() => talkListCon.value,() => {
      nextTick(() => {
        if(scrollbarRef.value && contentRef.value){
          scrollbarRef.value?.setScrollTop(contentRef.value.offsetHeight);
        }
        
      });
    },
    { deep: true }
  );
  
  const scrollbarRef = ref<any>(null);
  // 滚动到底部的方法
 
  
  onUnmounted(()=>{
    disconnect();
    printAddEnd();
  })
  
  
  
  
  
  
  
  
  defineExpose({
    sendSubmit,
    clearFun,
    creatNewTalk,
    getTalkCon
  })
</script>

<style lang="scss" scoped>
  $hvH: calc(var(--vh, 1vh) * 100);
  .send-textarea{
    position:relative; z-index:4; padding-right: 40px;
    :deep(.el-textarea__inner){box-shadow: none; padding: 0; transition: all ease 0.2s;}
     
  }
  .quan-textarea{
    :deep(.el-textarea__inner){height: calc( $hvH * 0.9 - 60px) !important;}
    .home-ri-top,.link-box{display: none;}
  }
.send-ziyuan{
  position: relative; background-color: #F3F4F6; border-radius: 10px; height: 33px; display: flex; align-items: center; justify-content: space-between; padding:0 10px; font-size: 13px;
  :deep(.local-icon){margin-left: 12px;}
  :deep(.el-select){
    position: absolute; width: 100%; left: 0; top: 0; height: 100%; width: 100%; z-index:10; opacity: 0 !important;
    .el-select__wrapper{
      box-shadow: none !important;
      
      .el-select__caret{color: #000;}
      .el-select__placeholder{color: #000;}
    }
  }
  
}
.send-bottom{
  overflow: hidden;border: 1px solid #000; border-radius: 16px; padding:10px 11px 0;
  .submit-box{
    display: flex; align-items: center; justify-content: space-between; border-radius: 4px; height: 42px; padding-bottom: 10px;
    .number{color: var(--el-text-color-placeholder); font-size: 12px;}
    
  }
  
  .sendCan{
    transition: all ease 0.3s; width:32px; height: 32px; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: not-allowed; background-color: #D6DEE8;
    &.on{cursor: pointer; background-color: var(--el-color-primary);}
    .curAnswerStop{width: 40%; height: 40%; background-color: #fff; border-radius: 4px;}
  }
}
.link-box{
  .title{
    display: flex; align-items: center; font-size: 18px; font-weight: bold; margin: 40px 0 30px;
    .icon{width: 20px; margin-right: 10px; margin-bottom: 3px;}
  }
  .link-list{display: flex; align-items: center;}
  .item{
    border-radius: 8px; border: 1px solid #C7C7C7; height: 88px; padding:12px; width: 24%; margin-right: 1%; cursor: pointer; transition: all ease .3s;
    &:hover{border-color: var(--el-color-primary);}
    .name{margin-bottom: 5px; font-weight: 500;}
    .intro{font-size: 12px;}
  }
}
.talk-content{
  &.on{
    height:calc($hvH - 60px); margin-bottom: 0; padding-bottom: 240px;
  }
  .talk-content-list{
    font-size: 16px;
    .item{
      display: flex; align-items: center; margin-bottom: 27px;
      &.w{
        justify-content: flex-end;
        .intro{background-color: var(--el-color-primary); color: #fff;}
      }
      &.h{
        justify-content: flex-start;
        .intro{padding: 0; width: 100%;}
      }
    }
    .tx{width: 32px; height: 32px; border-radius: 50%; margin-right: 10px;}
    .intro{ border-radius: 16px; padding: 16px 20px;}
    .stop{margin-top:8px}
  }
  :deep(.el-scrollbar__wrap){padding-top: var(--wap-pad);}
  :deep(.el-scrollbar__bar){display: none !important;}
}
.w-textarea{
  :deep(.el-textarea__inner){padding:0px; box-shadow:none !important; background-color: transparent; color: var(--el-text-color-primary);}
}
.bottom-box{ 
  width: 100%; left: 0; bottom: 10px; background-color: #fff; 
  .local-icon-new{color: var(--el-color-primary); padding-left:  8px !important; padding-right:  8px !important;}
  .create-btn{
    background-color: var(--el-color-primary-light-9) !important; padding: 4px 16px; margin: 0 auto; margin-bottom: 8px; border: 1px solid var(--el-color-primary-light-7); border-radius:6px; display: none;
    :deep(svg){margin-right: 6px;}
  }
  .form-tips{margin-top: 40px;}
  &.on{
    position: absolute;
    .create-btn{
      display: flex;
    }
  }
  .quan{
    position: absolute; right: 10px; top:0,;display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; z-index:90; cursor: pointer;
    .icon{display: block; width: 60%;}
    }
}
/* 对话顶部样式 */
.home-ri-top{
  background-color: var(--el-color-primary-light-9); padding:14px 40px; border-radius: 12px;
  .h2{font-size: 22px; font-weight: bold;}
  .intro{margin-right: 80px;}
}
@media only screen and (max-width: 769px){
  .quan-textarea{
    .bottom-box{height: $hvH; background-color: rgba(0,0,0,0.5); display: flex; align-items: flex-end; padding: 0; z-index: var(--zindex4); position: fixed;}
    .send-bottom{background-color: #fff; width: 100%; border: none; border-radius: 0.26rem 0.26rem 0 0; padding: 0.2rem;}
    .form-tips{display: none;}
    :deep(.el-textarea__inner){height: calc(84vh - 1rem) !important;}
    .create-btn{display: none !important;}
  }
  .model-box{display: block;}
  .link-box{display: none;}
  .ai-ziyuan-list{
    :deep(.el-scrollbar){max-height: calc($hvH - 3rem);}
    .item{
      padding:0.15rem var(--wap-pad); margin-bottom: 0.1rem;
      .name{font-size:0.34rem; color:#000;}
      .intro{font-size:0.26rem}
      &.on{background-color: #f8f8f8;}
      &.un{
        opacity: 0.65;
      }
    }
  }
  .zb-pup-bg{
    width: 100%; height: 100%; position: fixed; left: 100%; top:0; z-index: var(--zindex1); background-color: rgba(0, 0, 0, 0.5);
    transition: opacity ease .3s; opacity: 0;
    &.on{display: block; left: 0; opacity: 1;}
  }
  .zb-pup-box{
    background-color: #fff; border-radius: 0.3rem 0.3rem 0 0; position: fixed; left: 0; bottom: 0; width: 100%; z-index: var(--zindex2); overflow: hidden; transform: translateY(100%); transition: all ease .3s; 
    &.on{transform: translateY(0)}
    .title{font-size: 0.36rem; text-align: center; line-height: 1.4rem; margin-bottom: 0.1rem; font-weight: bold;}
    .close{
      position: absolute; right: 0; top:0.2rem; display: flex; align-items: center; justify-content: center; width: 40px; height:40px;
      :deep(.el-icon){font-size: 0.4rem !important;}
    }
  }
  
  
  .talk-content-list{
    .item{
      display: flex; align-items: center; margin-bottom: 0.2rem;
      .intro{padding: 0.16rem 0.2rem; border-radius: 0.16rem; font-size: 0.32rem;}
    }
    .stop{
      .talk-btn{
        color:#7F7F7F; font-size:0.26rem;
        span{margin-left: 0.1rem;}
      }
      :deep(.el-icon){font-size:0.26rem !important}
      
    }
  }
  .talk-content{
    &.on{height: calc($hvH - 3rem - var(--headerH) ) !important; padding-bottom: 0;}
  }
  .form-tips{line-height:1.4; margin-top:6px !important}
  .home-le{ width:100%}
  .talk-btn{font-size:12px;}
  .send-textarea{
    padding-right: 0.6rem;
    :deep(.el-textarea__inner){font-size: 0.30rem; color: #000;}
  }
  .bottom-box{
    padding:0.2rem calc(var(--wap-pad) * 0.8); bottom: var(--bottomH);  min-height: 2.15rem; position: fixed;
    .quan{right: 0.1rem; width: 0.55rem; height: 0.55rem; top: 0.1rem;}
  }
  
  /* 对话顶部样式 */
  .home-ri-top{
    padding:10px 0; border-radius: 6px; margin: var(--wap-pad); display: block; background-color: transparent;
    .h2{font-size: 15px; font-weight: bold; display: none; }
    .intro{font-size:12px; margin-right: 0; background-color: #F7F7F7; padding: 16px; border-radius: 12px; margin-top: 20px;}
    .web-img{display:none}
    .ai-kf-box{display: flex; align-items: center; justify-content: center; width: 90px; height: 90px; margin: 0 auto; background-color: var(--el-color-primary-light-9); border-radius: 28px;}
    .ai-kf-box img{width: 73px;}
  }
  .send-bottom{
    padding: 0.1rem 0.1rem 0 0.1rem; border-radius: 0.16rem;
    .sendCan{
      width: 0.55rem; height: 0.55rem; border-radius: 50%; background-color: var(--el-color-primary);
      :deep(.el-icon){font-size: 0.3rem !important;}
      &.on{color: #fff !important;}
      .curAnswerStop{width: 0.25rem; height: 0.25rem; border-radius: 0.06rem;}
      
      
    }
    
    .submit-box{
      height: 0.7rem; margin-top: 0.1rem;
      .web{display: none !important;}
      .send-ziyuan{
        min-width: 2rem; width: auto; cursor: pointer; display: flex; align-items: center; justify-content: space-between; padding: 0 0.2rem; background-color: #F3F4F6; border-radius: 0.2rem; height: 0.66rem;
        span{margin-right: 0.25rem; font-size: 0.26rem;}
      }
      :deep(.el-select){display: none;}
    }
  }
  
}
</style>